#include "mx22a.h"

static bt_info bt_info_current={0};

static uint8_t bt_rx_buffer[RX_BUF_SIZE]={0};

// 蓝牙模块初始化相关的 AT 指令
#define AT_RST					"AT+RESET\r\n"
#define AT_LENAME 				"AT+LENAME=SmartWatch\r\n"
#define AT_DNAME 				"AT+DNAME=SmartWatch\r\n"
#define AT_SPPOFF 				"AT+SPP=0\r\n"
#define AT_BLEOFF 				"AT+BLE=0\r\n"
#define AT_SPPON 				"AT+SPP=1\r\n"
#define AT_BLEON 				"AT+BLE=1\r\n"
#define AT_PINE 				"AT+PINE=0\r\n"
#define AT_SERV 				"AT+SERV=FFE1\r\n"
#define AT_NOTIFY 				"AT+NOTIFY=FFE2\r\n"
#define AT_WRITE 				"AT+WRITE=FFE3\r\n"
#define AT_LEMAC				"AT+LEMAC?\r\n"	

/**
  * @brief 获取当前蓝牙信息
  * @param None
  * @retval 返回指向当前蓝牙信息的指针
  */
bt_info * bt_get_current_info()
{
	return &bt_info_current;
}

/**
  * @brief 获取蓝牙接收DMA缓冲区
  * @param None
  * @retval 返回蓝牙接收缓冲区的指针
  */
uint8_t * bt_get_rx_dma_buffer()
{
	return bt_rx_buffer;
}

/**
  * @brief 发送无响应的命令
  * @param cmd 发送的命令字符串
  * @retval 如果发送成功返回1，失败返回0
  */
_Bool send_com_NoResp(uint8_t *cmd)
{
    if (HAL_UART_Transmit_DMA(&BT_UART_HANDLE, cmd, strlen((char *)cmd)) == HAL_OK) {  // 发送数据到蓝牙模块
        return 1;  // 返回成功
    }
    return 0;  // 返回失败
}

/**
  * @brief 向蓝牙模块发送AT指令并等待响应
  * @param at_command AT指令字符串
  * @param res 期望的响应字符串
  * @param retry 重试次数
  * @param xWait 等待时间
  * @retval 如果收到预期响应返回1，超时或未匹配返回0
  */
_Bool send_at_command(uint8_t *at_command,uint8_t* res, uint8_t retry, TickType_t xWait)
{
//    BaseType_t RxFlag = errQUEUE_EMPTY;
//    rx_struct rx_msg;
//
//    while(retry--)  // 重试指定次数
//    {
//    	HAL_UART_Transmit_DMA(&BT_UART_HANDLE, at_command, strlen((char *)at_command));  // 发送AT命令
//
//        RxFlag = xQueueReceive(BT_RES_RX_QUEUE_HANDLE, &rx_msg, xWait);  // 从接收队列读取数据
//
//        if(RxFlag == errQUEUE_EMPTY)  // 如果没有收到数据
//            continue;
//
//        if(strstr((const char*)rx_msg.rx_data,(const char *)res) != NULL)  // 如果响应匹配
//            return 1;  // 成功
//    }
//    return 0;  // 超时或未匹配

	BaseType_t RxFlag = errQUEUE_EMPTY;
	rx_struct rx_msg;

	while(retry--)  // 重试指定次数
	{
		HAL_UART_Transmit_DMA(&BT_UART_HANDLE,at_command, strlen((char *)at_command));  // 发送AT命令

		RxFlag = xQueueReceive(BT_RES_RX_QUEUE_HANDLE, &rx_msg, xWait);  // 从接收队列读取数据

		if(RxFlag == errQUEUE_EMPTY)  // 如果没有收到数据
			continue;

		if(strstr((const char*)rx_msg.rx_data,(const char *)res) != NULL)  // 如果响应匹配
			return 1;  // 成功

		if (strstr((const char*)rx_msg.rx_data, "ERR") != NULL)  // 如果收到错误响应
			return -1;  // 返回错误
	}
	return 0;  // 超时或未匹配
}

/**
  * @brief 向蓝牙模块发送命令并接收响应
  * @param cmd 要发送的命令
  * @param res 期望的响应
  * @param retry 重试次数
  * @param xWait 等待时间
  * @param outBuf 输出缓冲区
  * @param outLen 输出缓冲区的长度
  * @retval 返回1表示成功，-1表示发生错误，0表示超时
  */
int send_com_WithResp(uint8_t* cmd, uint8_t* res, uint8_t retry, TickType_t xWait, uint8_t* outBuf, size_t * outLen)
{
    rx_struct rx_msg;
    memset(rx_msg.rx_data, 0, RX_BUF_SIZE);  // 清空接收缓冲区
    BaseType_t RxFlag = errQUEUE_EMPTY;

    // 接收并检测返回内容
    while (retry--)  // 重试指定次数
    {

		// 通过UART发送数据
		HAL_UART_Transmit_DMA(&BT_UART_HANDLE, cmd, strlen((char *)cmd));

        RxFlag = xQueueReceive(BT_RES_RX_QUEUE_HANDLE, &rx_msg, xWait);  // 从接收队列读取数据

        if (RxFlag == errQUEUE_EMPTY)  // 如果没有收到数据
            continue;

        if (strstr((const char*)rx_msg.rx_data, (const char *)res) != NULL)  // 如果响应匹配
        {
            memcpy(outBuf, (const char*)rx_msg.rx_data, rx_msg.data_len);  // 拷贝返回数据
            *outLen = (size_t)rx_msg.data_len;  // 设置输出数据长度
            return 1;  // 成功
        }
        
        if (strstr((const char*)rx_msg.rx_data, "ERR") != NULL)  // 如果收到错误响应
        {
            memcpy(outBuf, (const char*)rx_msg.rx_data, rx_msg.data_len);  // 拷贝错误信息
            *outLen = (size_t)rx_msg.data_len;
            return -1;  // 返回错误
        }
    }

    return 0;  // 超时或未匹配
}

/**
  * @brief 获取蓝牙设备地址
  * @param bt_address 输出蓝牙地址的缓冲区
  * @retval 如果获取成功返回1，否则返回0
  */
_Bool get_BTAdd(uint8_t *bt_address)
{
    uint8_t msg[30] = {0};
    
    // 发送 AT 指令，获取蓝牙地址
    if (send_com_WithResp((uint8_t *)AT_LEMAC, (uint8_t *)"+LEMAC:", 10, 10, msg, NULL))
    {
        // 查找 "+LEMAC:" 的位置
        char *prefix = strstr((const char *)msg, "+LEMAC:");
        if (prefix != NULL)
        {
            // 移动指针到地址部分
            prefix += strlen("+LEMAC:");
            
            // 确保地址长度合法（蓝牙地址通常 12 个字符）
            if (strlen(prefix) >= 12)
            {
                strncpy((char *)bt_address, prefix, 12);  // 拷贝12字节地址
                bt_address[12] = '\0'; // 可选，添加字符串终止符
                return 1;  // 成功
            }
        }
    }

    return 0;  // 失败
}

/**
  * @brief 初始化蓝牙模块
  * @param None
  * @retval 如果初始化成功返回1，否则返回0
  */
_Bool ble_module_init()
{
	xQueueReset(BT_COM_RX_QUEUE_HANDLE);
	xQueueReset(BT_RES_RX_QUEUE_HANDLE);
	
    if(!get_BTAdd(bt_info_current.BT_Add))
        return 0;  // 如果获取地址失败，返回0

    printf("%s\r\n", bt_info_current.BT_Add);  // 打印获取的蓝牙地址
    
    // 定义AT命令初始化序列
    struct
    {
        char* cmd;     // AT命令字符串
        char* res;     // 成功响应关键字
        char* desc;    // 用于打印的步骤说明
        uint8_t retry; // 每条命令的最大重试次数
    } cmdList[] =
    {
//    	{AT_RST, "OK", "AT_RST", 10},
        {AT_SPPOFF, "OK", "AT_SPPOFF", 10},
        {AT_BLEOFF, "OK", "AT_BLEOFF", 10},
        {AT_LENAME, "OK", "AT_LENAME", 10},
        {AT_DNAME, "OK", "AT_DNAME", 10},
        {AT_PINE, "OK", "AT_PINE", 10},
        {AT_SERV, "OK", "AT_SERV", 10},
        {AT_NOTIFY, "OK", "AT_NOTIFY", 10},
        {AT_WRITE, "OK", "AT_WRITE", 10},
		{AT_SPPON, "OK", "AT_SPPOON", 10},
        {AT_BLEON, "OK", "AT_BLEOON", 10}
    };
    
    // 遍历并发送所有AT初始化命令
    for(int i = 0; i < sizeof(cmdList) / sizeof(cmdList[0]); i++)
    {
        if(!send_at_command((uint8_t*)cmdList[i].cmd, (uint8_t *)cmdList[i].res, cmdList[i].retry, 100))
        {
            printf("%s FAIL\r\n", cmdList[i].desc);  // 如果命令发送失败
            return 0;  // 初始化失败
        }
        printf("%s OK\r\n", cmdList[i].desc);  // 命令发送成功
        vTaskDelay(100);  // 延时100ms
    }
    BT_Disconnect(); //确保断开连接
    return 1;  // 初始化成功
}

/**
  * @brief UART 接收中断回调函数
  * @param huart UART句柄
  * @param Size 接收数据的大小
  * @retval None
  */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if (huart == &BT_UART_HANDLE)
    {
        rx_struct rx_msg_packet={0};

        memcpy(rx_msg_packet.rx_data, bt_rx_buffer, Size);  // 将接收到的数据存入结构体
        rx_msg_packet.data_len = Size;  // 设置接收到的数据长度

        // 推送到队列
        if (strstr((const char*)rx_msg_packet.rx_data, "@C@") != NULL)
        {
            xQueueSendToBackFromISR(BT_COM_RX_QUEUE_HANDLE, &rx_msg_packet, NULL);  // 如果是指令数据，发送到指令队列
        }
        else
        {
            xQueueSendToBackFromISR(BT_RES_RX_QUEUE_HANDLE, &rx_msg_packet, NULL);  // 否则发送到响应队列
        }

        // 继续接收数据
        HAL_UARTEx_ReceiveToIdle_DMA(&BT_UART_HANDLE, bt_rx_buffer, RX_BUF_SIZE);
        __HAL_DMA_DISABLE_IT(BT_UART_HANDLE.hdmarx, DMA_IT_HT);  // 禁用DMA传输一半中断
    }
}
